/************************************************************
 * Project Name         [Thinking_In_Java]
 * File Name            [EditMenuListener.java]
 * Creation Date        [11-Jul-2014]
 * 
 * Copyright© ge.y.yang@gmail.com All Rights Reserved
 * 
 * Work hard, play harder, think big and keep fit
 ************************************************************/
package pkg_02_gui.notepad_V1.ui.edit;

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;

import pkg_02_gui.notepad_V1.ui.main.NotepadFrame;

/**
 * 
 * @author 不落的太阳(Sean Yang)
 * @version 1.0
 * @since JDK 6
 * 
 */
public class EditMenuListener extends EditMenu implements ActionListener,
		DocumentListener, MouseListener {

	private static final long serialVersionUID = 4233036392809865872L;

	private JTextArea textArea = null; // 文本框
	private EditMenuPopup EditMenuPopup = null; // 弹出菜单
	private EditMenuToolBar editToolBar = null; // 菜单栏

	private final UndoManager undoManager = new UndoManager(); // 撤销管理器
	private final Clipboard clipBoard = Toolkit.getDefaultToolkit()
			.getSystemClipboard();// 创建系统剪贴板

	/**
	 * 持有对方引用, 供替换对话框使用
	 */
	private NotepadFrame frame = null;

	/**
	 * 为菜单项添加监听器
	 */
	private void addListenerToItem() {
		getUndoItem().addActionListener(this);
		getRedoItem().addActionListener(this);
		getCutItem().addActionListener(this);
		getCopyItem().addActionListener(this);
		getPasteItem().addActionListener(this);
		getDeleteItem().addActionListener(this);
		getFindItem().addActionListener(this);
		getFindNextItem().addActionListener(this);
		getReplaceItem().addActionListener(this);
		getTurnToItem().addActionListener(this);
		getAllSelectedItem().addActionListener(this);
		getDateTimeItem().addActionListener(this);
		// 为文本域添加监听器
		textArea.addMouseListener(this);
	}

	/**
	 * 添加浮动工具栏到窗口
	 */
	private void addToolbarToPanel() {
		frame.getToolbarPanel().add(editToolBar);
	}

	public EditMenuListener(String menuName, JTextArea textArea,
			NotepadFrame frame) {
		super(menuName);
		EditMenuPopup = new EditMenuPopup(this); // 初始化弹出菜单
		editToolBar = new EditMenuToolBar(this); // 初始化浮动菜单
		this.textArea = textArea;
		this.frame = frame;
		addListenerToItem();
		undoFunction();
		addToolbarToPanel();
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		/** **************************撤销*************************** */
		if (e.getSource() == getUndoItem()
				|| e.getSource() == EditMenuPopup.getUndo()
				|| e.getSource() == editToolBar.getUndoButton()) {
			textArea.requestFocusInWindow();
			if (undoManager.canUndo()) {
				try {
					undoManager.undo();
					getUndoItem().setEnabled(true);
				} catch (CannotUndoException ex) {
					System.out.println("Unable to undo" + ex);
				}
			}
			if (!undoManager.canUndo()) {
				getUndoItem().setEnabled(false);
			}
		}
		/** **************************恢复撤销*************************** */
		if (e.getSource() == getRedoItem()
				|| e.getSource() == EditMenuPopup.getRedo()
				|| e.getSource() == editToolBar.getRedoButton()) {
			textArea.requestFocusInWindow();
			if (undoManager.canRedo()) {
				try {
					undoManager.redo();
					getRedoItem().setEnabled(true);
				} catch (CannotRedoException ex) {
					System.out.println("Unable to redo" + ex);
				}
			}
			if (!undoManager.canRedo()) {
				getRedoItem().setEnabled(false);
			}
		}
		/** **************************剪切*************************** */
		if (e.getSource() == getCutItem()
				|| e.getSource() == EditMenuPopup.getCut()
				|| e.getSource() == editToolBar.getCutButton()) {
			textArea.requestFocusInWindow();
			textArea.cut();
			checkMenuItemEnabled();// 检查菜单的可用性
		}
		/** **************************复制*************************** */
		if (e.getSource() == getCopyItem()
				|| e.getSource() == EditMenuPopup.getCopy()
				|| e.getSource() == editToolBar.getCopyButton()) {
			textArea.requestFocusInWindow();
			textArea.copy();
			checkMenuItemEnabled(); // 检查菜单的可用性
		}
		/** **************************粘贴*************************** */
		if (e.getSource() == getPasteItem()
				|| e.getSource() == EditMenuPopup.getPaste()
				|| e.getSource() == editToolBar.getPasteButton()) {
			textArea.requestFocusInWindow();
			textArea.paste();
			checkMenuItemEnabled();// 检查菜单的可用性
		}
		/** **************************删除*************************** */
		if (e.getSource() == getDeleteItem()
				|| e.getSource() == EditMenuPopup.getDelete()) {
			textArea.requestFocusInWindow();
			String copyText = textArea.getSelectedText();// 获取当前选中文本
			if (copyText != null) {
				textArea.replaceSelection("");
			}
			checkMenuItemEnabled(); // 检查菜单的可用性
		}
		/** **************************查找*************************** */
		if (e.getSource() == getFindItem()) {
			textArea.requestFocusInWindow();
			searchAndReplace();
		}
		/** ***********************查找下一个************************* */
		if (e.getSource() == getFindNextItem()) {
			textArea.requestFocusInWindow();
			searchAndReplace();
		}
		/** **************************替换*************************** */
		if (e.getSource() == getReplaceItem()) {
			textArea.requestFocusInWindow();
			searchAndReplace();
		}
		/** **************************转到*************************** */
		if (e.getSource() == getTurnToItem()) {
			textArea.requestFocusInWindow();
			// 未实现
		}
		/** **************************全选*************************** */
		if (e.getSource() == getAllSelectedItem()
				|| e.getSource() == EditMenuPopup.getSelectAll()) {
			textArea.requestFocusInWindow();
			textArea.selectAll();

		}
		/** **************************时间日期*************************** */
		if (e.getSource() == getDateTimeItem()) {
			SimpleDateFormat timeFormat = new SimpleDateFormat(
					"yyyy年MM月dd日 HH时mm分ss秒");
			Calendar currentDate = Calendar.getInstance();
			// 将日期时间插入到当前光标处
			textArea.insert(timeFormat.format(currentDate.getTime()),
					textArea.getCaretPosition());
		}
	}

	/**
	 * 设置菜单的可用性: 剪切, 复制, 粘贴, 删除功能
	 */
	private void checkMenuItemEnabled() {
		// 通过判断编辑区是否有文本选中来设置剪切, 复制, 删除的可用性
		// 通过判断剪贴板信息设置粘贴选项的可用性
		String selectedText = textArea.getSelectedText();
		if (selectedText == null) {
			// 编辑菜单
			getCutItem().setEnabled(false);
			getCopyItem().setEnabled(false);
			getDeleteItem().setEnabled(false);
			// 弹出菜单
			EditMenuPopup.getCut().setEnabled(false);
			EditMenuPopup.getCopy().setEnabled(false);
			EditMenuPopup.getDelete().setEnabled(false);
			// 浮动工具栏
			editToolBar.getCutButton().setEnabled(false);
			editToolBar.getCopyButton().setEnabled(false);
		} else {
			// 编辑菜单
			getCutItem().setEnabled(true);
			getCopyItem().setEnabled(true);
			getDeleteItem().setEnabled(true);
			// 弹出菜单
			EditMenuPopup.getCut().setEnabled(true);
			EditMenuPopup.getCopy().setEnabled(true);
			EditMenuPopup.getDelete().setEnabled(true);
			// 浮动工具栏
			editToolBar.getCutButton().setEnabled(true);
			editToolBar.getCopyButton().setEnabled(true);
		}

		// 获得剪贴板内容
		Transferable contents = clipBoard.getContents(null);
		if (contents == null) {
			getPasteItem().setEnabled(false);// 编辑菜单
			EditMenuPopup.getPaste().setEnabled(false);// 弹出菜单
			editToolBar.getPasteButton().setEnabled(false); // 浮动工具栏
		} else {
			getPasteItem().setEnabled(true);// 编辑菜单
			EditMenuPopup.getPaste().setEnabled(true);// 弹出菜单
			editToolBar.getPasteButton().setEnabled(true); // 浮动工具栏
		}
	}

	/**
	 * 实现撤销功能
	 */
	private void undoFunction() {
		// 实现撤销功能
		textArea.getDocument().addUndoableEditListener(
				new UndoableEditListener() {
					@Override
					public void undoableEditHappened(UndoableEditEvent e) {
						undoManager.addEdit(e.getEdit());
					}
				});
		textArea.getDocument().addDocumentListener(this);// 添加监听器
	}

	/**
	 * 实现DocumentListener中的方法
	 */
	@Override
	public void changedUpdate(DocumentEvent e) {
		getUndoItem().setEnabled(true);// 编辑菜单
		EditMenuPopup.getUndo().setEnabled(true);// 弹出菜单
		editToolBar.getUndoButton().setEnabled(true);// 浮动工具栏
	}

	@Override
	public void insertUpdate(DocumentEvent e) {
		getUndoItem().setEnabled(true);// 编辑菜单
		EditMenuPopup.getUndo().setEnabled(true);// 弹出菜单
		editToolBar.getUndoButton().setEnabled(true);// 浮动工具栏
	}

	@Override
	public void removeUpdate(DocumentEvent e) {
		getUndoItem().setEnabled(true);// 编辑菜单
		EditMenuPopup.getUndo().setEnabled(true);// 弹出菜单
		editToolBar.getUndoButton().setEnabled(true);// 浮动工具栏
	}

	/**
	 * 实现MouseListener中的方法
	 */
	@Override
	public void mouseClicked(MouseEvent e) {
		checkMenuItemEnabled();
	}

	@Override
	public void mouseEntered(MouseEvent e) {
	}

	@Override
	public void mouseExited(MouseEvent e) {
		checkMenuItemEnabled();
	}

	@Override
	public void mousePressed(MouseEvent e) {
	}

	/**
	 * 弹出菜单
	 */
	@Override
	public void mouseReleased(MouseEvent e) {
		if (e.isPopupTrigger()) {
			// getY()返回事件相对于源组件的垂直y坐标
			// getYOnScreen()返回事件的绝对垂直y坐标
			EditMenuPopup.show(frame, e.getX(), e.getY());
		}
	}

	public JTextArea getTextArea() {
		return textArea;
	}

	/**
	 * 查找与替换
	 */
	private void searchAndReplace() {
		final JDialog findDialog = new JDialog(frame, "查找与替换", true);
		Container container = findDialog.getContentPane();
		container.setLayout(new FlowLayout(FlowLayout.LEFT));

		final JLabel searchContentLabel = new JLabel("查找内容(N)");
		final JLabel replaceContentLabel = new JLabel("替换为(P)");

		final JTextField searchField = new JTextField(30); // "查找"输入栏
		final JTextField replaceField = new JTextField(30);// "替换"输入栏
		final JCheckBox matchCase = new JCheckBox("区分大小写(C)");

		ButtonGroup group = new ButtonGroup();
		final JRadioButton up = new JRadioButton("向上(U)");
		final JRadioButton down = new JRadioButton("向下(R)");
		down.setSelected(true);// 设置向下为默认选中
		group.add(up);
		group.add(down);

		final JButton searchNext = new JButton("查找下一个(F)");// "查找下一个按钮"
		final JButton replace = new JButton("替换(R)");// "替换"按钮
		final JButton replaceAll = new JButton("全部替换(A)");// "全部替换"按钮
		final JButton cancel = new JButton("取消");// 取消按钮

		/**
		 * "替换"按钮事件
		 */
		replace.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (replaceField.getText().length() == 0 // 如果要替换的内容为空
						&& textArea.getSelectedText() != null) {
					textArea.replaceSelection("");
				}
				if (replaceField.getText().length() > 0
						&& textArea.getSelectedText() != null) {
					textArea.replaceSelection(replaceField.getText());
				}
			}
		});

		/**
		 * "替换全部"按钮事件
		 */
		replaceAll.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				textArea.setCaretPosition(0); // 将光标放在编辑区开头
				int temp1 = 0;
				int temp2 = 0;
				int replaceCount = 0;

				if (searchField.getText().length() == 0) {
					JOptionPane.showMessageDialog(findDialog, "请填写查找内容", "提示",
							JOptionPane.WARNING_MESSAGE);
					searchField.requestFocus();// 获得焦点
					return;
				}

				while (temp1 > -1) {
					int findStartPosition = textArea.getCaretPosition();
					String str1 = textArea.getText(); // 待查找的文本
					String str2 = str1.toLowerCase();
					String str3 = searchField.getText(); // 查找关键字
					String str4 = str3.toLowerCase();
					String strA, strB;

					if (matchCase.isSelected()) {// 判断是否区分大小写查找
						strA = str1;
						strB = str3;
					} else {
						strA = str2;
						strB = str4;
					}

					if (up.isSelected()) {// 根据查找方向来截取内容
						if (textArea.getSelectedText() == null) {
							temp1 = strA.lastIndexOf(strB,
									findStartPosition - 1);
						} else {
							temp1 = strA.lastIndexOf(strB, findStartPosition
									- searchField.getText().length() - 1);
						}
					} else if (down.isSelected()) {
						if (textArea.getSelectedText() == null) {
							temp1 = strA.indexOf(strB, findStartPosition);
						} else {
							temp1 = strA.indexOf(strB, findStartPosition
									- searchField.getText().length() + 1);
						}
					}

					if (temp1 > -1) {
						if (up.isSelected()) {
							textArea.setCaretPosition(temp1);// 设置光标位置
							temp2 = searchField.getText().length();
							textArea.select(temp1, temp1 + temp2);
						} else if (down.isSelected()) {
							textArea.setCaretPosition(temp1);// 设置光标位置
							temp2 = searchField.getText().length();
							textArea.select(temp1, temp1 + temp2);
						}
					} else {
						if (replaceCount == 0) {
							JOptionPane.showMessageDialog(findDialog,
									"您要查找的内容不存在!", "记事本",
									JOptionPane.INFORMATION_MESSAGE);
						} else {
							JOptionPane.showMessageDialog(findDialog, "成功替换"
									+ replaceCount + "个匹配内容", "替换成功",
									JOptionPane.INFORMATION_MESSAGE);
						}
					}

					if (replaceField.getText().length() == 0
							&& textArea.getSelectedText() != null) {
						textArea.replaceSelection("");
						replaceCount++;
					}
					if (replaceField.getText().length() > 0
							&& textArea.getSelectedText() != null) {
						textArea.replaceSelection(replaceField.getText());
						replaceCount++;
					}
				}
			}
		});

		/**
		 * "查找下一个"事件
		 */
		searchNext.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				int temp1 = 0;
				int temp2 = 0;
				if (searchField.getText().length() == 0) {
					JOptionPane.showMessageDialog(findDialog, "请填写查找内容!", "提示",
							JOptionPane.WARNING_MESSAGE);
					searchField.requestFocus(true);
					return;
				}
				int findStartPosition = textArea.getCaretPosition();// 获得光标位置

				String str1 = textArea.getText();
				String str2 = str1.toLowerCase();
				String str3 = searchField.getText();
				String str4 = str3.toLowerCase();
				String strA, strB;

				if (matchCase.isSelected()) {// 区分大小写被选中
					strA = str1;
					strB = str3;
				} else {
					strA = str2;
					strB = str4;
				}

				if (up.isSelected()) {
					if (textArea.getSelectedText() == null) {
						temp1 = strA.lastIndexOf(strB, findStartPosition - 1);
					} else {
						temp1 = strA.lastIndexOf(strB, findStartPosition
								- searchField.getText().length() - 1);
					}
				} else if (down.isSelected()) {
					if (textArea.getSelectedText() == null) {
						temp1 = strA.indexOf(strB, findStartPosition);
					} else {
						temp1 = strA.indexOf(strB, findStartPosition
								- searchField.getText().length() + 1);
					}
				}
				if (temp1 > -1) {
					if (up.isSelected()) {
						textArea.setCaretPosition(temp1);
						temp2 = searchField.getText().length();
						textArea.select(temp1, temp1 + temp2);
					} else if (down.isSelected()) {
						textArea.setCaretPosition(temp1);
						temp2 = searchField.getText().length();
						textArea.select(temp1, temp1 + temp2);
					}
				} else {
					JOptionPane.showMessageDialog(null, "您要查找的内容不存在!", "记事本",
							JOptionPane.INFORMATION_MESSAGE);
				}
			}
		});

		/**
		 * 取消对话框
		 */
		cancel.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				findDialog.dispose();
			}
		});

		JPanel topPanel = new JPanel();// 查找面板
		topPanel.add(searchContentLabel);
		topPanel.add(searchField);
		topPanel.add(searchNext);

		JPanel replacePanel = new JPanel();// 替换面板
		replacePanel.setLayout(new GridLayout(1, 2));
		replacePanel.add(replace);
		replacePanel.add(replaceAll);

		JPanel centerPanel = new JPanel();
		centerPanel.add(replaceContentLabel);
		centerPanel.add(replaceField);

		JPanel direction = new JPanel();// 搜索方向面板
		direction.setBorder(BorderFactory.createTitledBorder("方向"));
		direction.add(up);
		direction.add(down);

		JPanel bottomPanel = new JPanel();
		bottomPanel.add(matchCase); // 大小写识别
		bottomPanel.add(direction);// 方向
		bottomPanel.add(cancel);// 取消

		container.add(topPanel);
		container.add(centerPanel);
		container.add(bottomPanel);
		container.add(replacePanel);

		// 设置"查找与替换"对话框的大小, 可更改大小, 位置和可见性
		findDialog.setSize(550, 240);
		findDialog.setResizable(true);
		findDialog.setLocation(230, 280);
		findDialog.setVisible(true);

	}
}
